import crypto from 'node:crypto';
import fs from 'node:fs';
import path, { resolve } from 'node:path';

// 本地临时文件夹
const lyDir = './input';

// 自定义格式化函数(每行最多展示3个属性)
export const formatObject = (obj, propertiesPerLine = 3) => {
    const entries = Object.entries(obj);
    let result = '{\n';

    for (let i = 0; i < entries.length; i += propertiesPerLine) {
        const chunk = entries.slice(i, i + propertiesPerLine);
        const line = chunk.map(([key, value]) => `  "${key}": ${JSON.stringify(value)}`).join(', ');
        result += line + ',\n';
    }

    return result.length > 2 ? result.slice(0, -2) + '\n}' : result + '}'; // 移除最后一个逗号和换行符
};

// 创建一个promise，规定参数的最后一个是回调函数
export const getAwait = (func, ...arg) => {
    return new Promise(resolve => {
        func(...arg, (...res) => {
            resolve(res);
        });
    });
};

// 生成一个安全的随机字符串
export const getSecureRandomString = length => {
    // 定义可用的字符集
    const charset = 'acemnopqrsuvwxyz';

    // 创建一个 Buffer 来存储随机值
    const randomBytes = crypto.randomBytes(length);

    // 将随机值映射到字符集
    let result = '';
    for (let i = 0; i < length; i++) {
        const randomIndex = randomBytes[i] % charset.length;
        result += charset[randomIndex];
    }

    return result;
};

// 读取文件路径list文件返回数组
export const readList = fileListPath => {
    return fs
        .readFileSync(fileListPath, 'utf-8')
        .split('\n')
        .filter(Boolean)
        .map(str => str.replace("file '", '').replace(/'/, '').trim());
};

// 生成临时文件路径list文件
export const setFileList = (list, fileNameLen = 10, nameStr) => {
    // 生成 FFmpeg 输入文件列表
    const inputListStr = list.map(file => `file '${file}'`).join('\n');
    const filelistName = path.join(lyDir, (nameStr ? nameStr : getSecureRandomString(fileNameLen)) + '.txt');
    // 将文件列表写入临时文件
    fs.writeFileSync(filelistName, inputListStr);

    return filelistName;
};

// 删除文件
export const removeFileList = filelistName => {
    fs.unlinkSync(filelistName);
};

// 完整路径、改为文件名、改为的类型
export const rename = (name, nameX) => {
    fs.rename(name, nameX, error => {
        if (error) {
            console.log(`改名失败 ${name}:`, error);
        } else {
            console.log(`改名成功：从 ${name} 改为 ${nameX}`);
        }
    });
};

// 读取文件夹
export const readdir = async inputDir => {
    const [err, files] = await getAwait(fs.readdir, inputDir);
    if (err) {
        console.log('错误的文件夹内容:', err);
        return 'err';
    }
    return files;
};

// 判断一个路径是文件夹还是文件，还是other。1、文件 2、文件夹 0、其他
export const stat = async filePath => {
    // 判断这个路径是否存在
    const exists = fs.existsSync(filePath);
    if (!exists) {
        return 0;
    }
    const [err, stats] = await getAwait(fs.stat, filePath);
    if (err) {
        //  console.error(`无法访问路径: ${filePath}`, err);
        return 0;
    }
    if (stats.isFile()) {
        return 1;
    } else if (stats.isDirectory()) {
        return 2;
    } else {
        return 0;
    }
};

export const isNumericString = str => {
    return /^\d+$/.test(str);
};

// 处理影视工场的文件
export const ysgc = filePath => {
    return new Promise(resolve => {
        // 读取文件内容
        fs.readFile(filePath, 'utf8', (err, data) => {
            if (err) {
                console.error('读取文件错误:', err);
                return;
            }

            // 分割文件内容为行
            const lines = data.split('\n');

            // 用于存储.ts文件名的数组
            const tsFiles = [];

            // 遍历每一行，寻找.ts文件
            lines.forEach(line => {
                // 检查行中是否包含.ts文件扩展名
                if (line.includes('.ts')) {
                    // 提取文件名
                    const filename = line.split('/').pop();
                    // 将文件名添加到数组中
                    tsFiles.push(filename);
                }
            });

            // 输出.ts文件名的数组
            resolve(tsFiles);
        });
    });
};

// 把'00:00:00.123'、'00:00:00'这样的字符串转成秒数
export const timeStringToSeconds = timeString => {
    // 将时间字符串分割成小时、分钟和秒
    const parts = timeString.split(':');
    const hours = parseInt(parts[0], 10);
    const minutes = parseInt(parts[1], 10);
    const secondsPart = parts[2].split('.');

    const seconds = parseInt(secondsPart[0], 10);
    // 检查是否有毫秒部分
    const milliseconds = secondsPart.length > 1 ? parseFloat(`0.${secondsPart[1]}`) : 0;

    // 计算总秒数
    const totalSeconds = hours * 3600 + minutes * 60 + seconds + milliseconds;

    return totalSeconds;
};

// 将秒数转换为小时:分钟:秒格式
export const secondsToHms = seconds => {
    const hours = Math.floor(seconds / 3600);
    const minutes = Math.floor((seconds % 3600) / 60);
    const secs = Math.floor((seconds % 60) * 100) / 100;
    return `${hours}:${minutes}:${secs}`;
};

// 调用它创建一个节流函数，默认每300毫秒内只能执行一次
export const throttle = (func, limit = 300) => {
    let lastFunc;
    let lastRan;

    return function (...args) {
        const context = this;
        if (!lastRan) {
            // 如果是第一次调用，直接执行
            lastRan = Date.now();
        } else {
            // 清除之前的定时器
            clearTimeout(lastFunc);
            // 设置一个新的定时器
            lastFunc = setTimeout(
                () => {
                    if (Date.now() - lastRan >= limit) {
                        func.apply(context, args);
                        lastRan = Date.now();
                    }
                },
                limit - (Date.now() - lastRan)
            );
        }
    };
};

// 空字符串、null、undefined
export const isEmpty = value => {
    return value == null || value === '' || (value + '').trim().length == 0 || value === undefined;
};

// 创建一个回调函数
export const createCallback = (func, ...args) => {
    return () => {
        const fff = func(...args);
        return fff;
    };
};

// 定义一个队列方法
export class PromiseQueue {
    #queue;
    #isRunning;

    constructor() {
        this.queue = [];
        this.isRunning = false;
    }

    // 添加任务到队列
    enqueue(task) {
        this.queue.push(task);
        this.runNext();
    }

    // 执行下一个任务
    runNext() {
        if (!this.isRunning && this.queue.length > 0) {
            this.isRunning = true;
            const task = this.queue.shift(); // 移除队列中的第一个任务
            task()
                .then(() => {
                    this.isRunning = false;
                    this.runNext(); // 任务完成后，执行下一个任务
                })
                .catch(error => {
                    console.error('Task failed with error:', error);
                    this.isRunning = false;
                    this.runNext();
                });
        }
    }
}
